-module(aleph_server).

%%
%% Include files
%%
-include("aleph_service_macros.hrl").
-include("aleph_naming_macros.hrl").   
%%
%% Exported Functions
%%
-export([start_link/1,start_service_link/2,init/1,handle_cast/2,handle_info/2,handle_call/3]).
-export([terminate/2,start_service/3,remove_service/3,remove_service/2,invoke/4,shutdown/1]).
-export([start_service/2,remove_service/1,shutdown/0]).
-import(aleph_process_labeler,[init_labeler/0,label_application/1,label_process/1]).
-behaviour(supervisor).




%%%%intial functions
init([server,Application])->    
    {ok,Application};

init([supervisor,Application,Entry_servcie]) ->  
    aleph_process_labeler:init_labeler(),
    label_application(erlang:atom_to_list(Application)),
    Entry_spec={Entry_servcie,{aleph_server,start_service_link,[Entry_servcie,Application]},
           permanent, brutal_kill, worker, [aleph_server]},
    {ok, {{one_for_one, 0, 1}, [Entry_spec]}}. 

%%%%supervisor launcher
start_link(Application) ->
    %io:format("Application~p~n",[Application]),
    Entry_service=make_entry(Application),
    supervisor:start_link({local,Application},aleph_server, [supervisor,Application,Entry_service]),   
    Object=fun([Action,Module|Args])->
                   %io:format("Invoke Action[~p]@~p~n",[Action,self()]),
                   gen_server:cast(Entry_service,{Action,[Module,Args]});
              ([Action])->
                   gen_server:cast(Entry_service,{Action});
              (MODULE)->
                   fun([Action|Args])->
                         gen_server:call(Entry_service,{invoke,[MODULE,Action,Args]});
                      (Action)->
                         gen_server:call(Entry_service,{invoke,[MODULE,Action,[]]})
                   end
            end,
     Object.


%%%%entry process launcher
start_service_link(Entry_servcie,Application)->
    label_process(
                  gen_server:start_link({local,Entry_servcie},aleph_server, [server,Application], [] )).

 
%%%%entry process callbacks
-define(SERVICE_NAME,?name(aleph_server)).
?define_call2(start_service,Module,Args).
?define_cast1(remove_service,Module).
?define_cast(shutdown).
?gen_handle_call.
?gen_handle_cast.  
?gen_handle_info;
handle_info({'EXIT',_,Reason}, State) ->    
    {stop, Reason, State}. 
 
terminate(_,_)->  
    io:format("aleph_server closed~n"),
    ok. 
%%%entry process functions
start_service(Application,Module,[])->
    %io:format("start_service@~p~n",[self()]),
    Ret=supervisor:start_child(Application,Module:process_spec()),
    {reply,Ret,Application};
start_service(Application,Module,Args)->
    Ret=supervisor:start_child(Application,Module:process_spec(Args)),
    {reply,Ret,Application}.

remove_service(Application,Module)->
     remove_service(Application,Module,[]).
remove_service(Application,Module,[])->
      AppModule=aleph_process_labeler:get_name(atom_to_list(Module)),
      supervisor:terminate_child(Application,AppModule),
      {noreply,Application}.

shutdown(Application)->
    remove_all_service(),
    erlang:exit(self(),normal),
    {noreply,Application}.
                
invoke(Application,MODULE,Action,Args)->
    {reply,apply(MODULE,Action,Args),Application}.



%%%private functions
make_entry(Application)->
    erlang:list_to_atom(atom_to_list(Application)++"_aleph_server").

remove_all_service()->
    ok.
